package com.gitee.liuzhi.demo.other;

import lombok.*;

/**
 * Created by 2023/9/5/0005
 *
 * @Author LiuZhi
 * @Version V1.0
 * @Description Lombok 是一个 java 类库
 * <p>
 * 它利用注解方式自动生成 java bean 中 getter、setter、equals 等方法
 * 还能自动生成 logger、toString、hashCode、builder 等日志相关变量、Object 类方法或设计模式相关的方法, 能够让你的代码更简洁, 更美
 */
public class LombokDemo {

    /**
     * Getter and Setter
     * 使用Getter和/或Setter注释任何字段, 以使lombok自动生成默认的getter/setter
     * <p>
     * + 默认的getter只是返回该字段, 如果该字段被称为foo, 则名为getFoo (如果该字段的类型为boolean, 则为isFoo)
     * + 默认生成的getter/setter方法是公共的, 除非你明确指定一个AccessLevel, 合法访问级别为PUBLIC, PROTECTED, PACKAGE和PRIVATE
     */
    public static class GetterSetterExample {

        @Getter(value = AccessLevel.PRIVATE)
        @Setter(value = AccessLevel.PUBLIC)
        private int age = 10;

        @Setter(AccessLevel.PROTECTED)
        private String name;

    }

    /**
     * ToString
     * 使用@ToString注释, 以使lombok生成toString()方法的实现
     * <p>
     * + 默认情况下, 将打印所有非静态字段
     * + 如果要跳过某些字段, 可以使用@ToString.Exclude注释这些字段。或者, 可以通过使用@ToString（onlyExplicitlyIncluded = true）, 然后使用@ToString.Include标记要包含的每个字段, 来确切指定希望使用的字段
     * + 通过将callSuper设置为true, 可以将toString的超类实现的输出包含到输出中。请注意, java.lang.Object中toString()的默认实现几乎毫无意义
     */
    @ToString
    public static class ToStringExample {
        @ToString.Exclude
        private int id;
        private static final int STATIC_VAR = 10;
        private String name;
        private String[] tags;
    }


    /**
     * EqualsAndHashCode
     * 使用@EqualsAndHashCode进行注释, 以使lombok生成equals(Object other)和hashCode()方法的实现
     * <p>
     * + 默认情况下, 它将使用所有非静态, 非瞬态字段
     * + 可以通过使用@EqualsAndHashCode.Include或@EqualsAndHashCode.Exclude标记类型成员来修改使用哪些字段(甚至指定要使用各种方法的输出)
     * + 如果将@EqualsAndHashCode应用于扩展另一个类的类, 通常, 为此类自动生成equals和hashCode方法是一个坏主意, 因为超类还定义了字段, 该字段也需要equals/ ashCode代码, 但不会生成此代码。
     * 通过将callSuper设置为true, 可以在生成的方法中包括超类的equals和hashCode方法
     */
    @EqualsAndHashCode
    public static class EqualsAndHashCodeExample {
        private final transient int transientVar = 10;
        private String name;
        private double score;
        @EqualsAndHashCode.Exclude
        private String[] tags;
        @EqualsAndHashCode.Exclude
        private int id;
    }


    /**
     * RequiredArgsConstructor
     * 生成一个带有所需参数的构造函数
     * <p>
     * + 必需的参数是final字段和带有约束的字段 (会将类的每一个final字段或者non-null字段生成一个构造方法)
     * + 基于构造方法为属性赋值, 容器通过调用类的构造方法将其进行依赖注入 (写在类上面可以代替@AutoWired注解, 需要注意的是: 在注入的时候需要用final定义, 或者使用@notnull注解)
     */
    @RequiredArgsConstructor(staticName = "of")
    @AllArgsConstructor(access = AccessLevel.PROTECTED)
    @NoArgsConstructor(force = true)
    public static class ConstructorExample<T> {
        private int x, y;
        @NonNull
        private T description;

        @NoArgsConstructor(force = true)
        public static class NoArgsExample {
            @NonNull
            private String field;
        }
    }

    /**
     * Data
     */
    @Data
    public static class DataExample {
        private final String name;
        @Setter(AccessLevel.PACKAGE)
        private int age;
        private double score;
        private String[] tags;

        @ToString
        @Data(staticConstructor = "of")
        public static class Exercise<T> {
            private final String name;
            private final T value;
        }
    }


}
